/**
 * 		-	ad-creatif	-
 * 		-	20/07/2012	-
 *
 * This super class contains and define the common functions for all entities (hostiles or not)
 * 
 **/
package entities {

	import org.flixel.FlxPoint;
	import org.flixel.FlxSprite;
	import org.flixel.plugin.photonstorm.FlxDelay;
	
	import tools.MyFlxSprite;
	import tools.MyFlxWeapon;
	import tools.WeaponManager;
	
	
	public class Entity extends MyFlxSprite {
		
		protected var coolDown:Number 	//time before launching an attack
		
		public var _charging:Boolean;
		public var _crouching:Boolean;
		
		public var _invincible:Boolean;
		public var _isDying:Boolean;
		public var _destroyWall:Boolean;
		
		public var _attacking:Boolean;
		
		public var level:uint;
		public var name:String;
		public var weapon:MyFlxWeapon;
		public var infos:Object;
		public var abilities:Abilities;
		
		
		public function Entity(X:Number, Y:Number, infos:Object) {
			super(X, Y);
			this.infos = infos;
			name = infos.name;
			
			// graphics are undefined
			if(!infos.tile) infos['tile'] = {};
			if(!infos.tile.tileSheet){ infos.tile['tileSheet'] = (new Registry.blankTilesPNG).bitmapData;trace('ALERTE : tileSheet not found for', infos.name);}
			if(!infos.tile.tileSize) {infos.tile.tileSize = new Array(50,50);trace('ALERTE : tileSize n\'est pas défini pour le calque', infos.name);}
			if(!infos.tile.realSize) {infos.tile.realSize = infos.tile.tileSize;trace('ALERTE : realSize n\'est pas défini pour le calque', infos.name);}
			if(!infos.tile.offset) {infos.tile.offset = [0,0];trace('ALERTE : offset n\'est pas défini pour le calque', infos.name);}
			
			if(!infos.gamePlay)infos['gamePlay'] = {};
			if(!infos.gamePlay.health) infos.gamePlay.health = 1; 
			
			// tileSize is undefined
			if(!infos.tile.tileSize) {
				trace('ALERTE : tileSize n\'est pas défini pour le calque', infos.name);
				infos.tile.tileSize = new Array(50,50);
			}
			
			
			loadGraphicWithBitmap(infos.tile.tileSheet, true, true, infos.tile.tileSize[0], infos.tile.tileSize[1]);
			width = infos.tile.realSize ? infos.tile.realSize[0] : infos.tile.tileSize[0];
			height = infos.tile.realSize ? infos.tile.realSize[1] : infos.tile.tileSize[1];
			offset = new FlxPoint(infos.tile.offset ? infos.tile.offset[0] : 0 , infos.tile.offset ? infos.tile.offset[1] : 0);
			
			// create animations
			if (infos.anims.walk)		addAnimation("walk", infos.anims.walk, 9, true); 
			else { infos.anims.walk = [0]; addAnimation("walk",  infos.anims.walk, 11, true);}
			
			if (infos.anims.idle) 		addAnimation("idle", infos.anims.idle, 2, true); 
			else { infos.anims.idle = [0]; addAnimation("idle",  infos.anims.idle, 11, true);}
			
			if (infos.anims.crouch) 	addAnimation("crouch", infos.anims.crouch, 10, true); 
			else addAnimation("crouch", infos.anims.walk, 11, true) ;
			
			if (infos.anims.crouchIdle) addAnimation("crouchIdle", infos.anims.crouchIdle, 1, true); 
			else addAnimation("crouchIdle", infos.anims.idle, 2, true);
			
			if (infos.anims.charge) 	addAnimation("charge", infos.anims.charge, 9, false)  
			else addAnimation("charge", infos.anims.walk, 11, false) ;
			
			if (infos.anims.jump) 		addAnimation("jump", infos.anims.jump, 6, false);  
			else addAnimation("jump", infos.anims.walk, 11, true) ;
			
			if (infos.anims.attack) 	addAnimation("attack", infos.anims.attack, 20, false) 
			else addAnimation("attack", infos.anims.idle, 6, true) ;
			
			if (infos.anims.attackWalk) addAnimation("attackWalk", infos.anims.attackWalk, 20, true) 
			else  addAnimation("attackWalk", infos.anims.walk, 11, true);
			
			coolDown = 0;
			abilities = new Abilities(this);
		
			// setting gameplay datas
			if(infos.gamePlay.destroyWall) _destroyWall = true;
			if(infos.gamePlay.acceleration) acceleration.x = maxVelocity.x = infos.gamePlay.acceleration;
			if(infos.gamePlay.deceleration) drag.x = infos.gamePlay.deceleration;
			acceleration.y = Registry.gameInfos.world.gravity;
			health = infos.gamePlay.health;
		
			if(infos.attack.weaponsName) {
				weapon = WeaponManager.addWeapon(infos.attack.weaponsName[0], this);
			}
			
			// adding to the state
			switch(infos.type){
				case 'AI_minion':
				case 'AI_boss':
				case 'AI_simple':
					Registry.enemyPool.add(this);
					break;
				case 'player':
				default :
					Registry.friendlyPool.add(this);
			}
		}
		
	
		
		/**
		 * this is where the entity is leveling up 
		 * @param	healthMode	if true, it'll define the level depending of the amount of life (often used for the bosses)
		 * @return	nothing	
		 * */
		public function levelUp(healthMode:Boolean = false):void {
			
			if(!Registry.abilities[name]) return;
			else var abilities:Object = Registry.abilities[name];
					
			
			if(!healthMode) {
				level ++;
				health = infos.gamePlay.health;
			} else {
				for (var key:String in abilities) {
					var healthTrigger:Number = infos.gamePlay.health * abilities[key]['trigger'] / 100;
					if(health < healthTrigger && parseInt(key) > level){
						level = parseInt(key);
					} 
				}	
			} 
			
			//updating coolDown
			if(abilities[level]) coolDown = abilities[level].coolDown;
			
			// updtating abilities list
			this.abilities.setAllowedAbilities();
			
			trace(name, 'won a level, now level : ', level);
		}
		
		
		
		
		
		
		/**
		 * update here, will just set the shooting position depending of the offset given
		 * */
		
		override public function update():void {
			super.update();
			if (weapon) weapon.setParent(this, "x", "y", ((this.facing == RIGHT) ? parseInt(infos.attack.weaponOffset[0]) : 0), infos.attack.weaponOffset[1]);			
		}
		
		override public function hurt(Damage:Number):void {
			if(_invincible) return;
			super.hurt(Damage);
			if(infos.sounds.hurt && !_isDying)infos.sounds.hurt.play();
			
			if(infos.gamePlay.healthMode) levelUp(true);
			abilities.attack('invincibility');
		}
		
		
		
		
		override public function kill():void {
			super.kill();
			Registry.entityPool.remove(this,true);
			velocity.x = 0;
			velocity.y = 0; 
			angle=0;
		}
		
		
		
		
	}
}
